using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Reflection;
using System.Runtime.Remoting;
using Common.Shared.Xml.Wddx;

namespace Common.Shared.Reflection {
	public static class TypeUtils {

		public static bool IsNumeric ( Type type ) {
			return ( type == typeof ( int ) || type == typeof ( short ) ||
				type == typeof ( long ) || type == typeof ( double ) ||
				type == typeof ( byte ) || type == typeof ( float ) ||
				type == typeof ( decimal ) || type == typeof ( uint ) ||
				type == typeof ( ushort ) || type == typeof ( ulong ) ||
				type == typeof ( UIntPtr ) || type == typeof ( IntPtr ) );
		}

		public static bool IsPrimitive ( Type t ) {
			return t == typeof ( string ) || TypeUtils.IsNumeric ( t ) || t == typeof ( bool );
		}

		public static bool IsString ( Type t ) {
			return IsTypeOf<string> ( t );
		}

		public static bool IsTypeOf<T> ( Type t ) {
			return typeof ( T ) == t;
		}

		public static bool CanSerialize ( Type type ) {
			ConstructorInfo ci = type.GetConstructor ( new Type[] { } );
			return ci != null || IsValueType ( type ) || IsCollection ( type );
		}

		public static long GetIntPtrValue ( IntPtr ptr ) {
			return ptr.ToInt64 ( );
		}

		public static ulong GetUIntPtrValue ( UIntPtr ptr ) {
			return ptr.ToUInt64 ( );
		}

		public static bool IsValueType ( Type type ) {
			return ( type == typeof ( String ) || type == typeof ( Boolean ) ||
				IsNumeric ( type ) || type == typeof ( Guid ) ) || type.IsPrimitive;
		}

		public static bool IsCollection ( Type type ) {
			return ( type.IsGenericType && type.GetGenericTypeDefinition ( ).Equals ( typeof ( List<> ) ) || type.IsAssignableFrom ( typeof ( IList ) ) );
		}

		public static bool IsNullable ( Type type ) {
			return ( type.IsGenericType && type.GetGenericTypeDefinition ( ).Equals ( typeof ( Nullable<> ) ) );
		}

		public static object CreateInstance ( string fullName ) {
			string[] data = fullName.Split ( new char[] { ',' },2, StringSplitOptions.RemoveEmptyEntries );
			string typeName = data[ 0 ];
			string assemblyName = typeof ( TypeUtils ).Assembly.GetName ( ).FullName;
			if ( data.Length == 2 ) {
				assemblyName = data[ 1 ];
			}

			Assembly assembly = Assembly.Load ( assemblyName );
			Type type = null;
			if ( assembly != null ) {
				type = assembly.GetType ( typeName, false, true );
				if ( type != null ) {
					return Activator.CreateInstance ( type );
				}
			}
			return null;
		}

		public static WddxObject CreateWddxObject ( Type type ) {
			if ( type.IsSubclassOf(typeof ( WddxObject ) ) ) {
				return type.Assembly.CreateInstance ( type.FullName, true ) as WddxObject;
			} else {
				Console.WriteLine ( "unable to create type: {0}", type.FullName );
				return null;
			}
		}

		public static bool IsValidType ( string fullName ) {
			string[] data = fullName.Split ( new char[] { ',' },2, StringSplitOptions.RemoveEmptyEntries );
			string typeName = data[ 0 ];
			string assemblyName = typeof ( TypeUtils ).Assembly.GetName ( ).FullName;
			if ( data.Length == 2 ) {
				assemblyName = data[ 1 ];
			}

			Assembly assembly = Assembly.Load ( assemblyName );
			Type type = null;
			if ( assembly != null ) {
				type = assembly.GetType ( typeName, false, true );
				return type != null && type.IsSerializable;
			} else {
				return false;
			}
		}
	}

}
